package org.zhouhe.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;

import org.apache.ibatis.builder.xml.dynamic.DynamicSqlSource;
import org.apache.ibatis.builder.xml.dynamic.TextSqlNode;
import org.apache.ibatis.executor.parameter.DefaultParameterHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.log4j.Logger;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.zhouhe.model.PaginationBean;

@Repository
@SuppressWarnings({"unchecked", "rawtypes"})
public class MybatisDao extends SqlSessionDaoSupport{
	
	private static final String QUERY_COUNT_SUFFIX = "_COUNT";
	
	private static Logger logger = Logger.getLogger(MybatisDao.class);
	
	@Autowired
	public void autoWireSqlSessionFactory(SqlSessionFactory sqlSessionFactory){
		super.setSqlSessionFactory(sqlSessionFactory);
	}

	/**
	 * 分页查询
	 * 
	 * @作者： zhouhe
	 * @param sqlId Mybatis中配置的SQL-ID
	 * @param page 要查询的是第几页
	 * @param rows 每页显示记录数
	 * @param paramObject 查询参数
	 * @return PaginationBean
	 */
	public PaginationBean getListByPage(String sqlId, Integer page, Integer rows, Object paramObject) {
		long start = System.currentTimeMillis();
		PaginationBean pageBean = new PaginationBean();
		//获得最大行数
		String countSqlId = sqlId + QUERY_COUNT_SUFFIX;
		Configuration cfg = this.getSqlSession().getConfiguration();
		
		//注意：如果查询语句比较特殊（例如使用Distinct、Group、Union等复杂用法），请自己编写查询总数据的SQL，ID=sqlName + “_count”
		if(cfg.hasStatement(countSqlId)){//用户定义了查询记录总数的SQL
			Integer total = this.getSqlSession().selectOne(countSqlId, paramObject);
			pageBean.setTotal(total);
		}else{//用户没有定义了查询总数的SQL，分析原查询语句，并生成查询总数的SQL，查询记录总数。
			MappedStatement dataStmt = cfg.getMappedStatement(sqlId);
			SqlSource sqlSourceOld = dataStmt.getSqlSource();
			
			BoundSql boundSql = sqlSourceOld.getBoundSql(paramObject);
			String sql = boundSql.getSql().replace("\r", " ").replace("\n", " ").replace("\t", " ");
			int pos = sql.toLowerCase().indexOf(" from ");
			String sqlCount = "select count(0) "+ sql.substring(pos);
			SqlSource sqlSource = new DynamicSqlSource(cfg, new TextSqlNode(sqlCount));
			try {
				Connection connection = cfg.getEnvironment().getDataSource().getConnection();
				DefaultParameterHandler dp = new DefaultParameterHandler(dataStmt, paramObject,sqlSourceOld.getBoundSql(paramObject));
				PreparedStatement countStmt = connection.prepareStatement(sqlSource.getBoundSql(paramObject).getSql());    
				dp.setParameters(countStmt);
				ResultSet rs= countStmt.executeQuery();
				int rowCount = -1;
				if(rs.next()){
					rowCount =rs.getInt(1);
					logger.debug("==> page size sql: "+ sqlCount);
					logger.debug("==> page size: "+ rowCount);
					pageBean.setTotal(rowCount);
				}
				rs.close();    
				countStmt.close();
				connection.close();
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		logger.debug("query page sise:"+ (System.currentTimeMillis()-start));
		if(page == null || page < 1){
			page = 1;
		}
		if(rows == null || rows < 1){
			rows = 20;
		}
		List rowData = this.getSqlSession().selectList(sqlId, paramObject, new RowBounds((page-1)*rows, rows));
		pageBean.setRows(rowData);
		logger.debug("query page sise and data:"+ (System.currentTimeMillis()-start));
		return pageBean;
	}
}
